\input cweb.tex
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
% Project : GUSI   - Grand Unified Socket Interface
% File  : GUSI.web  - Documentation
% Author : Matthias Neeracher
% Started : 08Sep92        Language : C SpiderWeb
% Modified : 08Sep92 MN It's beginning to take shape
%     05Oct92 MN More or less complete now
%     13Dec92 MN Brush it up for release
%     09Jan93 MN Update for 1.0.1
%     22Feb93 MN Update for 1.1.0
%     06Jun93 MN Expurgate docu
%     20Jun93 MN Update for 1.2.0
%     20Jun93 MN Last minute changes for 1.2.0
%     30Jul93 MN Update for 1.3.0
% Last  : 30Jul93
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

% Copyright 1992, 1993 Matthias Neeracher <neeri@iis.ee.ethz.ch>

% This file is part of GUSI

% Here is TeX material that gets inserted after \input webmac

% \message{OK, entering \string\batchmode...}
% \batchmode

\def\hang{\hangindent 3em\indent\ignorespaces}

\def\title{GUSI 1.3.0 Reference}
\def\contentspagenumber{1} % should be odd
\def\topofcontents{\null\vfill
  \titlefalse % include headline on the contents page
  \def\rheader{\hfil}
  \centerline{\ttitlefont GUSI \titlefont --- Grand Unified Socket Interface}
  \vfill
}

\def\onecollist#1{\halign{\quad$\triangleright$\ \vtop{
 \hsize=15cm\strut##\strut}\hfil\cr#1}}
\def\twocollist#1{\halign{\quad$\triangleright$\bf\ ##\hfil&\quad
 \vtop{\hsize=13cm\strut##\strut}\hfil\cr#1}}
\def\plainonecol#1{\halign{\quad
 \vtop{\hsize=15cm\strut##\strut}\hfil\cr#1}}
\def\plaintwocol#1{\halign{\quad##\hfil&\quad
 \vtop{\hsize=13cm\strut##\strut}\hfil\cr#1}}
\def\bibliolist#1{\halign{\quad\bf$[$##$]$\hfil&\quad
 \vtop{\hsize=13cm\strut##\strut}\hfil\cr#1}}
\parindent=0pt


\N1. = Introduction.  \.{GUSI} is an extension and partial replacement of the
\.{MPW} runtime library. Its main objective is to provide a more or less simple
and consistent interface across the following {\it communication domains}:

\medskip\twocollist{
Files&Ordinary Macintosh files and \.{MPW} pseudo devices.\cr
Unix&Memory based communication within a single machine (This name exists for
historical reasons).\cr
Appletalk&\.{ADSP} (and possibly in the future \.{DDP}) communication over a
network.\cr
PPC&Local and remote connections with the System 7 \.{PPC Toolbox}\cr
Internet&\.{TCP} and \.{UDP} connections over \.{MacTCP}.\cr
PAP&Connections with the \.{Printer Access Protocol}, typically to a networked
PostScript printer.\cr
}

\medskip
Additionally, \.{GUSI} adds some \.{UNIX} library calls dealing with files
which
were missing, like \CD{}$\\{chdir}(\,)$\DC{}, \CD{}$\\{getcwd}(\,)$\DC{}, %
\CD{}$\\{symlink}(\,)$\DC{}, and \CD{}$\\{readlink}(\,)$\DC{}, and
changes a few other library calls to behave more like their \.{UNIX}
counterparts.

The most recent version of \.{GUSI} may be obtained by anonymous ftp from
\.{nic.switch.ch} in the directory \.{software/mac/src/mpw\_c}.

There is also a mailing list devoted to discussions about \.{GUSI}. You can
join the
list by sending email to $<$gusi-request\AT!iis.ee.ethz.ch$>$.

\fi

\N2. 2 Copying.

\medskip Copyright \copyright\ 1992, 1993 Matthias Neeracher

\medskip Permission is granted to anyone to use this software for any
purpose on any computer system, and to redistribute it freely,
subject to the following restrictions:

\medskip\onecollist{
The author is not responsible for the consequences of use of
this software, no matter how awful, even if they arise
from defects in it.\cr
The origin of this software must not be misrepresented, either
by explicit claim or by omission.\cr
Altered versions must be plainly marked as such, and must not
be misrepresented as being the original software.\cr
}

\fi

\N3. 2 Design Objectives. \.{GUSI} was developed according to at least three
mutually conflicting standards:

\medskip\onecollist{
The definition of the existing C library.\cr
The behavior of the corresponding UNIX calls.\cr
The author's judgement, prejudices, laziness, and limited resources.\cr
}

\medskip
In general, the behavior of the corresponding UNIX library call was
implemented,
since this faciliates porting UNIX utilities to the Macintosh.

\fi

\N4. 2 Acknowledgements. I would like to thank all who have agreed to beta test
this
code and who have provided feedback.

\medskip The TCP/IP code in \.{GUSIINET.cp}, \.{GUSITCP.cp}, and \.{GUSIUDP.cp}
is
derived from a socket library written by Charlie Reiman $<$creiman%
\AT!ncsa.uiuc.edu$>$,
which in turn is based on code written by Tom Milligan $<$milligan%
\AT!madhaus.utcs.utoronto.ca$>$.

\medskip The PAP code in \.{GUSIPAP.cp} is derived from code written by Sak
Wathanasin
$<$sw\AT!nan.co.uk$>$.

\medskip Many of the header files in the \.{:include:} subdirectory are
borrowed from BSD Unix,
therefore: This product includes software developed by the University of
California,
Berkeley and its contributors.

\fi

\N5. = Installing and using GUSI. This section discusses how you can install
\.{GUSI} on your disk and use it for your programs.

\fi

\M6. To install \.{GUSI}, change in the MPW Shell to its directory and type:
\medskip
\.{BuildProgram Install $<$Enter$>$}
\medskip
This will install all necessary files in \.{\{CIncludes\}}, \.{\{CLibraries\}},
and
\.{\{RIncludes\}}, respectively. It will also install \.{/etc/services} in your
preferences
folder, prompting you if you have an older version there.

\fi

\M7. To use \.{GUSI}, include one or more of the following header files in your
program:
\medskip\plaintwocol{
\.{GUSI.h}&The main file. This includes almost everything else.\cr
\.{TFileSpec.h}&\CD{}$\\{FSSpec}$\DC{} manipulation routines.\cr
\.{dirent.h}&Routines to access all entries in a directory.\cr
\.{netdb.h}&Looking up TCP/IP host names.\cr
\.{netinet/in.h}&The address format for TCP/IP sockets.\cr
\.{sys/errno.h}&The errors codes returned by GUSI routines.\cr
\.{sys/ioctl.h}&Codes to pass to \CD{}$\\{ioctl}(\,)$\DC{}.\cr
\.{sys/socket.h}&Data types for socket calls.\cr
\.{sys/stat.h}&Getting information about files.\cr
\.{sys/types.h}&More data types.\cr
\.{sys/uio.h}&Data types for scatter/gather calls.\cr
\.{sys/un.h}&The address format for Unix domain sockets.\cr
\.{unistd.h}&Prototypes for most routines defined in GUSI.\cr
}

\fi

\M8. GUSI expects the Macintosh Toolbox to be initialized. This will happen
automatically
if you're writing an \.{MPW} tool or if you are linking with \.{SIOW} and are
forcing
a write to standard output or standard error before you are using any non-file %
\.{GUSI}
routines. Otherwise, you should init the Toolbox in the following way:
\Y\P $\\{InitGraf}((\\{Ptr})\amp\\{qd}.\\{thePort});$\6
$\\{InitFonts}(\,);$\6
$\\{InitWindows}(\,);$\6
$\\{InitMenus}(\,);$\6
$\\{TEInit}(\,);$\6
$\\{InitDialogs}(\\{nil});$\6
$\\{InitCursor}(\,);$\par
\fi

\M9. You have to link your program with the \.{GUSI} library, \.{\{CLibraries%
\}GUSI.o},
and optionally one or several {\it configuration files}. Currently, the
following
configuration files exist:
\medskip\plaintwocol{
\.{GUSI\_Everything.cfg}&Include code for everything defined in \.{GUSI}.\cr
\.{GUSI\_Appletalk.cfg}&Include code for AppleTalk sockets.\cr
\.{GUSI\_Internet.cfg}&Include code for MacTCP sockets.\cr
\.{GUSI\_PAP.cfg}&Include code for PAP sockets.\cr
\.{GUSI\_PPC.cfg}&Include code for PPC sockets.\cr
\.{GUSI\_Unix.cfg}&Include code for Unix domain sockets.\cr
}

\medskip If you don't specify any configuration files, only the file related
routines will be
included. It's important that these files appear {\it before} all other
libraries.
Linking with \.{GUSI} doesn't free you from linking in the standard libraries,
typically:
\medskip\plainonecol{
\.{\{Libraries\}Runtime.o}\cr
\.{\{Libraries\}Interface.o}\cr
\.{\{CLibraries\}StdCLib.o}\cr
\.{\{Libraries\}ToolLibs.o}\cr
}

\medskip You will get lots of warning messages about duplicate definitions, but
that's ok
(Which means I can't do anything about it).

\fi

\M10. You should also rez your program with \.{GUSI.r}. The section
``Resources'' below
discusses when and how to add your own configuration resource to customize %
\.{GUSI}
defaults.

\fi

\N11. = Overview. This section discusses the routines common to all, or almost
all
communication domains. These routines return \CD{}${-}\O{1}$\DC{} if an error
occurred,
and set the variable \CD{}$\\{errno}$\DC{} to an error code. On success, the
routines return \CD{}$\O{0}$\DC{}
or some positive value.

\medskip
Some common error codes are:
\medskip\plaintwocol{
\CD{}$\\{EBADF}$\DC{}&The descriptor number you passed doesn't refer to a valid
file or socket.\cr
\CD{}$\\{ENOMEM}$\DC{}&Some memory error occurred.\cr
\CD{}$\\{EINTR}$\DC{}&The user interrupted a lengthy operation by pressing
Command-Period.\cr
\CD{}$\\{ENOTCONN}$\DC{}&The socket is not connected and must be connected for
this operation.\cr
}

\fi

\N12. 2 Creating and destroying sockets. A socket is created with \CD{}$%
\\{socket}(\,)$\DC{} and destroyed
with \CD{}$\\{close}(\,)$\DC{}.

\fi

\M13. \CD{}$\&{int}\ \\{socket}(\&{int}\ \\{af},\;\&{int}\ \\{type},\;\&{int}\ %
\\{protocol})$\DC{} creates an endpoint for communication
and returns a descriptor. \CD{}$\\{af}$\DC{} specifies the communication domain
to be used. Valid
values are:
\medskip\plaintwocol{
\CD{}$\\{AF\_UNIX}$\DC{}&Communication internal to a single Mac.\cr
\CD{}$\\{AF\_INET}$\DC{}&TCP/IP, using \.{MacTCP}.\cr
\CD{}$\\{AF\_APPLETALK}$\DC{}&Appletalk, using ADSP.\cr
\CD{}$\\{AF\_PPC}$\DC{}&The Program-to-Program Communication Toolbox.\cr
}
\medskip
\CD{}$\\{type}$\DC{} specifies the semantics of the communication. The
following two types are
available:
\medskip\plaintwocol{
\CD{}$\\{SOCK\_STREAM}$\DC{}&A two way, reliable, connection based byte stream.%
\cr
\CD{}$\\{SOCK\_DGRAM}$\DC{}&Connectionless, unreliable messages of a fixed
maximum length.\cr
}
\medskip
\CD{}$\\{protocol}$\DC{} would be used to specify an alternate protocol to be
used with a socket.
In \.{GUSI}, however, this parameter is always ignored.
\medskip
Error codes:
\medskip\plaintwocol{
\CD{}$\\{EINVAL}$\DC{}&The \CD{}$\\{af}$\DC{} you specified doesn't exist.\cr
\CD{}$\\{EMFILE}$\DC{}&The descriptor table is full.\cr
}

\fi

\M14. \CD{}$\&{void}\ \\{close}(\&{int}\ \\{fd})$\DC{} removes the access path
associated with the descriptor, and
closes the file or socket if the last access path referring to it was removed.

\fi

\N15. 2 Prompting the user for an address. To give the user the opportunity of
entering
an address for a socket to be bound or connected to, the \CD{}$\\{choose}(\,)$%
\DC{} routine was
introduced in \.{GUSI}. This routine has no counterpart in UNIX
implementations.

\fi

\M16. \CD{}$\&{int}\ \\{choose}(\&{int}\ \\{dom},\;\&{int}\ \\{type},\;\&{char}%
\ {*}\\{prompt},\;\&{void}\ {*}\\{constraint},\;\&{int}\ \\{flags},\;\&{void}\
{*}\\{name},\;\&{int}\ {*}\\{nlen})$\DC{} puts up a modal dialog prompting the
user to
choose an address. \CD{}$\\{dom}$\DC{} specifies the communication domain, like
in \CD{}$\\{socket}$\DC{}.
\CD{}$\\{type}$\DC{} may be used by future communication domains to further
differentiate
within a domain, but is ignored by current domains. \CD{}$\\{prompt}$\DC{} is a
message that will
appear in the dialog. \CD{}$\\{constraint}$\DC{} may be used to restrict the
types of acceptable
addresses (For more information, consult the section of the communication
domain).
The following two \CD{}$\\{flags}$\DC{} are defined for most socket types:
\medskip\plaintwocol{
\CD{}$\\{CHOOSE\_DEFAULT}$\DC{}&Offer the contents passed in \CD{}$\\{name}$%
\DC{} as the default choice.\cr
\CD{}$\\{CHOOSE\_NEW}$\DC{}&Prompt for a new address, suitable for passing to %
\CD{}$\\{bind}(\,)$\DC{}. Default
is prompting for an existing address, to be used by \CD{}$\\{connect}(\,)$%
\DC{}.\cr
}
\medskip
\CD{}$\\{name}$\DC{} on input contains a default address if \CD{}$\\{CHOOSE%
\_DEFAULT}$\DC{} is set. On output, it
is set to the address chosen.
\medskip
Error codes:
\medskip\plaintwocol{
\CD{}$\\{EINVAL}$\DC{}&One of the \CD{}$\\{flags}$\DC{} is not (yet) supported
by this communications
domain. This error is never reported for \CD{}$\\{CHOOSE\_DEFAULT}$\DC{}, which
might get silently
ignored.\cr
\CD{}$\\{EINTR}$\DC{}&The user chose ``Cancel'' in the dialog.\cr
}

\fi

\N17. 2 Establishing connections between sockets. Before you can transmit data
on a
stream socket, it must be connected to a peer socket. Connection establishment
is
asymmetrical: The server socket registers its address with \CD{}$\\{bind}(\,)$%
\DC{}, calls \CD{}$\\{listen}(\,)$\DC{}
to indicate its willingness to accept connections and accepts them by calling
\CD{}$\\{accept}(\,)$\DC{}. The client socket, after possibly having registered
its address with
\CD{}$\\{bind}(\,)$\DC{} (This is not necessary for all socket families as some
will automatically
assign an address) calls \CD{}$\\{connect}(\,)$\DC{} to establish a connection
with a server.

It is possible, but not required, to call \CD{}$\\{connect}(\,)$\DC{} for
datagram sockets.

\fi

\M18. \CD{}$\&{int}\ \\{bind}(\&{int}\ \|s,\;\&{const}\ \&{struct}\ %
\\{sockaddr}\ {*}\\{name},\;\&{int}\ \\{namelen})$\DC{} binds a socket to its
address. The
format of the address is different for every socket family. For some families,
you
may ask the user for an address by calling \CD{}$\\{choose}(\,)$\DC{}.
\medskip
Error codes:
\medskip\plaintwocol{
\CD{}$\\{EAFNOSUPPORT}$\DC{}&\CD{}$\\{name}$\DC{} specifies an illegal address
family for this socket.\cr
\CD{}$\\{EADDRINUSE}$\DC{}&There is already another socket with this address.%
\cr
}

\fi

\M19. \CD{}$\&{int}\ \\{listen}(\&{int}\ \|s,\;\&{int}\ \\{qlen})$\DC{} turns a
socket into a listener. \CD{}$\\{qlen}$\DC{} determines
how many sockets can concurrently wait for a connection, but is ignored for
almost
all socket families.

\fi

\M20. \CD{}$\&{int}\ \\{accept}(\&{int}\ \|s,\;\&{struct}\ \\{sockaddr}\ {*}%
\\{addr},\;\&{int}\ {*}\\{addrlen})$\DC{} accepts a connection for a socket
{\it on a new socket} and returns the descriptor of the new socket. If \CD{}$%
\\{addr}$\DC{} is not
\CD{}$\\{NULL}$\DC{}, the address of the connecting socket will be assigned to
it.

You can find out if a connection is pending by calling \CD{}$\\{select}(\,)$%
\DC{} to find out if
the socket is ready for {\it reading}.
\medskip
Error codes:
\medskip\plaintwocol{
\CD{}$\\{ENOTCONN}$\DC{}&You did not call \CD{}$\\{listen}(\,)$\DC{} for this
socket.\cr
\CD{}$\\{EWOULDBLOCK}$\DC{}&The socket is nonblocking and no socket is trying
to connect.\cr
}

\fi

\M21. \CD{}$\&{int}\ \\{connect}(\&{int}\ \|s,\;\&{const}\ \&{struct}\ %
\\{sockaddr}\ {*}\\{addr},\;\&{int}\ \\{addrlen})$\DC{} tries to connect to the
socket whose
address is in \CD{}$\\{addr}$\DC{}. If the socket is nonblocking and the
connection cannot be
made immediately, \CD{}$\\{connect}(\,)$\DC{} returns \CD{}$\\{EINPROGRESS}$%
\DC{}. You can find out if the
connection has been established by calling \CD{}$\\{select}(\,)$\DC{} to find
out if
the socket is ready for {\it writing}.
\medskip
Error codes:
\medskip\plaintwocol{
\CD{}$\\{EAFNOSUPPORT}$\DC{}&\CD{}$\\{name}$\DC{} specifies an illegal address
family for this socket.\cr
\CD{}$\\{EISCONN}$\DC{}&The socket is already connected.\cr
\CD{}$\\{EADDRNOAVAIL}$\DC{}&There is no socket with the given address.\cr
\CD{}$\\{ECONNREFUSED}$\DC{}&The socket refused the connection.\cr
\CD{}$\\{EINPROGRESS}$\DC{}&The socket is nonblocking and the connection is
being established.\cr
}

\fi

\N22. 2 Transmitting data between sockets. You can write data to a socket using
\CD{}$\\{write}(\,)$\DC{},
\CD{}$\\{writev}(\,)$\DC{}, \CD{}$\\{send}(\,)$\DC{}, \CD{}$\\{sendto}(\,)$%
\DC{}, or \CD{}$\\{sendmsg}(\,)$\DC{}. You can read data from a socket
using \CD{}$\\{read}(\,)$\DC{}, \CD{}$\\{readv}(\,)$\DC{}, \CD{}$\\{recv}(\,)$%
\DC{}, \CD{}$\\{recvfrom}(\,)$\DC{}, or \CD{}$\\{recvmsg}(\,)$\DC{}.

\fi

\M23. \CD{}$\&{int}\ \\{read}(\&{int}\ \|s,\;\&{char}\ {*}\\{buffer},\;%
\&{unsigned}\ \\{buflen})$\DC{} reads up to \CD{}$\\{buflen}$\DC{} bytes from
the socket. \CD{}$\\{read}(\,)$\DC{} for sockets differs from \CD{}$\\{read}(%
\,)$\DC{} for files mainly in that it
may read fewer than the requested number of bytes without waiting for the rest
to
arrive.
\medskip
Error codes:
\medskip\plaintwocol{
\CD{}$\\{EWOULDBLOCK}$\DC{}&The socket is nonblocking and there is no data
immediately available.\cr
}

\fi

\M24. \CD{}$\&{int}\ \\{readv}(\&{int}\ \|s,\;\&{const}\ \&{struct}\ \\{iovec}\
{*}\\{iov},\;\&{int}\ \\{count})$\DC{} performs the same
action, but scatters the input data into the \CD{}$\\{count}$\DC{} buffers of
the \CD{}$\\{iov}$\DC{}narray, always
filling one buffer completely before proceeding to the next. \CD{}$\\{iovec}$%
\DC{} is defined as
follows:
\Y\P $\&{struct}\ \\{iovec}\ \{\1$\6
$\\{caddr\_t}\ \\{iov\_base};$\5
\C{ Address of this buffer }\6
$\&{int}\ \\{iov\_len};$\5
\C{ Length of the buffer }\2\6
$\};$\par
\fi

\M25. \CD{}$\&{int}\ \\{recv}(\&{int}\ \|s,\;\&{void}\ {*}\\{buffer},\;\&{int}\
\\{buflen},\;\&{int}\ \\{flags})$\DC{} is identical to \CD{}$\\{read}(\,)$%
\DC{},
except for the \CD{}$\\{flags}$\DC{} parameter. If the \CD{}$\\{MSG\_OOB}$\DC{}
flag is set for a stream socket
that supports out-of-band data, \CD{}$\\{recv}(\,)$\DC{} reads out-of-band
data.

\fi

\M26. \CD{}$\&{int}\ \\{recvfrom}(\&{int}\ \|s,\;\&{void}\ {*}\\{buffer},\;%
\&{int}\ \\{buflen},\;\&{int}\ \\{flags},\;\&{void}\ {*}\\{from},\;\&{int}\ {*}%
\\{fromlen})$\DC{}
is the equivalent of \CD{}$\\{recv}(\,)$\DC{} for unconnected datagram sockets.
If \CD{}$\\{from}$\DC{} is not
\CD{}$\\{NULL}$\DC{}, it will be set to the address of the sender of the
message.

\fi

\M27. \CD{}$\&{int}\ \\{recvmsg}(\&{int}\ \|s,\;\&{struct}\ \\{msghdr}\ {*}%
\\{msg},\;\&{int}\ \\{flags})$\DC{} is the most general routine,
combining the possibilities of \CD{}$\\{readv}(\,)$\DC{} and \CD{}$%
\\{recvfrom}(\,)$\DC{}. \CD{}$\\{msghdr}$\DC{} is defined as
follows:
\Y\P $\&{struct}\ \\{msghdr}\ \{\1$\6
$\\{caddr\_t}\ \\{msg\_name};$\5
\C{ Like $\\{from}$ in $\\{recvfrom}(\,)$ }\6
$\&{int}\ \\{msg\_namelen};$\5
\C{ Like $\\{fromlen}$ in $\\{recvfrom}(\,)$ }\6
$\&{struct}\ \\{iovec}\ {{*}}\\{msg\_iov};$\5
\C{ Scatter/gather array }\6
$\&{int}\ \\{msg\_iovlen};$\5
\C{ Number of elements in $\\{msg\_iov}$ }\6
$\\{caddr\_t}\ \\{msg\_accrights};$\5
\C{ Access rights sent/received. Not used in \.{GUSI}}\6
$\&{int}\ \\{msg\_accrightslen};$\2\6
$\};$\par
\fi

\M28. \CD{}$\&{int}\ \\{write}(\&{int}\ \|s,\;\&{char}\ {*}\\{buffer},\;%
\&{unsigned}\ \\{buflen})$\DC{} writes up to \CD{}$\\{buflen}$\DC{} bytes to
the socket. As opposed to \CD{}$\\{read}(\,)$\DC{}, \CD{}$\\{write}(\,)$\DC{}
for nonblocking sockets always blocks
until all bytes are written or an error occurs.

\medskip
Error codes:
\medskip\plaintwocol{
\CD{}$\\{EWOULDBLOCK}$\DC{}&The socket is nonblocking and data can't be
immediately written.\cr
}

\fi

\M29. \CD{}$\&{int}\ \\{writev}(\&{int}\ \|s,\;\&{const}\ \&{struct}\ \\{iovec}%
\ {*}\\{iov},\;\&{int}\ \\{count})$\DC{} performs the same
action, but gathers the output data from the \CD{}$\\{count}$\DC{} buffers of
the \CD{}$\\{iov}$\DC{}narray, always
sending one buffer completely before proceeding to the next.

\fi

\M30. \CD{}$\&{int}\ \\{send}(\&{int}\ \|s,\;\&{void}\ {*}\\{buffer},\;\&{int}\
\\{buflen},\;\&{int}\ \\{flags})$\DC{} is identical to \CD{}$\\{write}(\,)$%
\DC{},
except for the \CD{}$\\{flags}$\DC{} parameter. If the \CD{}$\\{MSG\_OOB}$\DC{}
flag is set for a stream socket
that supports out-of-band data, \CD{}$\\{send}(\,)$\DC{} sends an out-of-band
message.

\fi

\M31. \CD{}$\&{int}\ \\{sendto}(\&{int}\ \|s,\;\&{void}\ {*}\\{buffer},\;%
\&{int}\ \\{buflen},\;\&{int}\ \\{flags},\;\&{void}\ {*}\\{to},\;\&{int}\ {*}%
\\{tolen})$\DC{}
is the equivalent of \CD{}$\\{send}(\,)$\DC{} for unconnected datagram sockets.
The message will
be sent to the socket whose address is given in \CD{}$\\{to}$\DC{}.

\fi

\M32. \CD{}$\&{int}\ \\{sendmsg}(\&{int}\ \|s,\;\&{const}\ \&{struct}\ %
\\{msghdr}\ {*}\\{msg},\;\&{int}\ \\{flags})$\DC{} combines the possibilities
of \CD{}$\\{writev}(\,)$\DC{} and \CD{}$\\{sendto}(\,)$\DC{}.

\fi

\N33. 2 I/O multiplexing.

\fi

\M34. \CD{}$\&{int}\ \\{select}(\&{int}\ \\{width},\;\\{fd\_set}\ {{*}}%
\\{readfds},\;\\{fd\_set}\ {{*}}\\{writefds},\;\\{fd\_set}\ {{*}}\\{exceptfds},%
\;\&{struct}\ \\{timeval}\ {*}\\{timeout})$\DC{} examines the I/O descriptors
specified
by the bit masks \CD{}$\\{readfs}$\DC{}, \CD{}$\\{writefs}$\DC{}, and \CD{}$%
\\{exceptfs}$\DC{} to see if they are ready for
reading, writing, or have an exception pending. \CD{}$\\{width}$\DC{} is the
number of significant
bits in the bit mask. \CD{}$\\{select}(\,)$\DC{} replaces the bit masks with
masks of those descriptors
which are ready and returns the total number of ready descriptors. \CD{}$%
\\{timeout}$\DC{}, if
not \CD{}$\\{NULL}$\DC{}, specifies the maximum time to wait for a descriptor
to become ready. If
\CD{}$\\{timeout}$\DC{} is \CD{}$\\{NULL}$\DC{}, \CD{}$\\{select}(\,)$\DC{}
waits indefinitely. To do a poll, pass a pointer to
a zero \CD{}$\\{timeval}$\DC{} value in \CD{}$\\{timeout}$\DC{}. Any of \CD{}$%
\\{readfds}$\DC{}, \CD{}$\\{writefds}$\DC{}, or \CD{}$\\{exceptfds}$\DC{}
may be given as \CD{}$\\{NULL}$\DC{} if no descriptors are of interest.
\medskip
Error codes:
\medskip\plaintwocol{
\CD{}$\\{EBADF}$\DC{}&One of the bit masks specified an invalid descriptor.\cr
}

\fi

\M35. The descriptor bit masks can be manipulated with the following macros:

\Y\P $\\{FD\_ZERO}(\\{fds});$\5
\C{ Clear all bits in ${{*}}\\{fds}$ }\6
$\\{FD\_SET}(\|n,\;$\39$\\{fds});$\5
\C{ Set bit $\|n$ in ${{*}}\\{fds}$ }\6
$\\{FD\_CLR}(\|n,\;$\39$\\{fds});$\5
\C{ Clear bit $\|n$ in ${{*}}\\{fds}$ }\6
$\\{FD\_ISSET}(\|n,\;$\39$\\{fds});$\5
\C{ Return $\O{1}$ if bit $\|n$ in ${{*}}\\{fds}$ is set, else $\O{0}$ }\par
\fi

\N36. 2 Getting and changing properties of sockets. You can obtain the address
of a
socket and the socket it is connected to by calling \CD{}$\\{getsockname}(\,)$%
\DC{} and
\CD{}$\\{getpeername}(\,)$\DC{} respectively. You can query and manipulate
other properties of a
socket by calling \CD{}$\\{ioctl}(\,)$\DC{}, \CD{}$\\{fcntl}(\,)$\DC{}, \CD{}$%
\\{getsockopt}(\,)$\DC{}, and \CD{}$\\{setsockopt}(\,)$\DC{}. You
can create additional descriptors for a socket by calling \CD{}$\\{dup}(\,)$%
\DC{} or \CD{}$\\{dup2}(\,)$\DC{}.

\fi

\M37. \CD{}$\&{int}\ \\{getsockname}(\&{int}\ \|s,\;\&{struct}\ \\{sockaddr}\
{*}\\{name},\;\&{int}\ {*}\\{namelen})$\DC{} returns in \CD{}${{*}}\\{name}$%
\DC{} the address
the socket is bound to. \CD{}${{*}}\\{namelen}$\DC{} should be set to the
maximum length of \CD{}$\\{name}$\DC{} and
will be set by \CD{}$\\{getsockname}(\,)$\DC{} to the actual length of the
name.

\fi

\M38. \CD{}$\&{int}\ \\{getpeername}(\&{int}\ \|s,\;\&{struct}\ \\{sockaddr}\
{*}\\{name},\;\&{int}\ {*}\\{namelen})$\DC{} returns in \CD{}${{*}}\\{name}$%
\DC{} the address
of the socket that this socket is connected to. \CD{}${{*}}\\{namelen}$\DC{}
should be set to the
maximum length of \CD{}$\\{name}$\DC{} and will be set by \CD{}$%
\\{getpeername}(\,)$\DC{} to the actual length
of the name.

\fi

\M39. \CD{}$\&{int}\ \\{ioctl}(\&{int}\ \|d,\;\&{unsigned}\ \&{int}\ %
\\{request},\;\&{long}\ {*}\\{argp})$\DC{} performs various operations
on the socket, depending on the \CD{}$\\{request}$\DC{}. The following codes
are valid for all
socket families:
\medskip\plaintwocol{
\CD{}$\\{FIONBIO}$\DC{}&Make the socket blocking if the \CD{}$\&{long}$\DC{}
pointed to by argp is \CD{}$\O{0}$\DC{}, else
make it nonblocking.\cr
\CD{}$\\{FIONREAD}$\DC{}&Set \CD{}${{*}}\\{argp}$\DC{} to the number of bytes
waiting to be read.\cr
}
\medskip
Error codes:
\medskip\plaintwocol{
\CD{}$\\{EOPNOTSUPP}$\DC{}&The operation you requested with \CD{}$\\{request}$%
\DC{} is not supported by this
socket family.\cr
}

\fi

\M40. \CD{}$\&{int}\ \\{fcntl}(\&{int}\ \|s,\;\&{unsigned}\ \&{int}\ \\{cmd},\;%
\&{int}\ \\{arg})$\DC{} provides additional control over a
socket. The following values of \CD{}$\\{cmd}$\DC{} are defined for all socket
families:
\medskip\plaintwocol{
\CD{}$\\{F\_DUPFD}$\DC{}&Return a new descriptor $\ge$ \CD{}$\\{arg}$\DC{}
which refers to the same socket.\cr
\CD{}$\\{F\_GETFL}$\DC{}&Return descriptor status flags.\cr
\CD{}$\\{F\_SETFL}$\DC{}&Set descriptor status flags to \CD{}$\\{arg}$\DC{}.\cr
}
\medskip
The only status flag implemented is \CD{}$\\{FNDELAY}$\DC{} which is true if
the socket is
nonblocking.
\medskip
Error codes:
\medskip\plaintwocol{
\CD{}$\\{EOPNOTSUPP}$\DC{}&The operation you requested with \CD{}$\\{cmd}$\DC{}
is not supported by this
socket family.\cr
}

\fi

\M41. \CD{}$\&{int}\ \\{getsockopt}(\&{int}\ \|s,\;\&{int}\ \\{level},\;\&{int}%
\ \\{optname},\;\&{void}\ {*}\\{optval},\;\&{int}\ {*}\\{optlen})$\DC{} is
used to request information about sockets. It is not implemented in \.{GUSI}.

\fi

\M42. \CD{}$\&{int}\ \\{setsockopt}(\&{int}\ \|s,\;\&{int}\ \\{level},\;\&{int}%
\ \\{optname},\;\&{void}\ {*}\\{optval},\;\&{int}\ \\{optlen})$\DC{} is used
to set options associated with a socket. It is not implemented in \.{GUSI}.

\fi

\M43. \CD{}$\&{int}\ \\{dup}(\&{int}\ \\{fd})$\DC{} returns a new descriptor
referring to the same socket as \CD{}$\\{fd}$\DC{}.
The old and new descriptors are indistinguishible. The new descriptor will
always
be the smallest free descriptor.

\fi

\M44. \CD{}$\&{int}\ \\{dup2}(\&{int}\ \\{oldfd},\;\&{int}\ \\{newfd})$\DC{}
closes \CD{}$\\{newfd}$\DC{} if it was open and makes it
a duplicate of \CD{}$\\{oldfd}$\DC{}. The old and new descriptors are
indistinguishible.

\fi

\N45. = Detail Description. This section discusses for each socket domain the
routines
that behave different from their description in the previous section and a few
calls
specific to one domain.

\fi

\N46. 2 File system calls. Files are unlike sockets in many respects: Their
length is
never changed by other processes, they can be rewound. There are also many
calls which
are specific to files.

\fi

\N47. 4 Differences to generic behavior.

\fi

\M48. The following calls make no sense for files and return an error of \CD{}$%
\\{EOPNOTSUPP}$\DC{}:
\medskip\plainonecol{
\CD{}$\\{socket}(\,)$\DC{}\cr
\CD{}$\\{bind}(\,)$\DC{}\cr
\CD{}$\\{listen}(\,)$\DC{}\cr
\CD{}$\\{accept}(\,)$\DC{}\cr
\CD{}$\\{connect}(\,)$\DC{}\cr
\CD{}$\\{getsockname}(\,)$\DC{}\cr
\CD{}$\\{getpeername}(\,)$\DC{}\cr
\CD{}$\\{getsockopt}(\,)$\DC{}\cr
\CD{}$\\{setsockopt}(\,)$\DC{}\cr
}

\fi

\M49. The following calls {\it will} work, but might be frowned upon by your
friends
(besides, UNIX systems generally wouldn't like them):
\medskip\plainonecol{
\CD{}$\\{recv}(\,)$\DC{}\cr
\CD{}$\\{recvfrom}(\,)$\DC{}\cr
\CD{}$\\{recvmsg}(\,)$\DC{}\cr
\CD{}$\\{send}(\,)$\DC{}\cr
\CD{}$\\{sendto}(\,)$\DC{}\cr
\CD{}$\\{sendmsg}(\,)$\DC{}\cr
}

\fi

\M50. \CD{}$\\{choose}(\,)$\DC{} returns zero terminated C strings in \CD{}$%
\\{name}$\DC{}.
It accepts an additional flag \CD{}$\\{CHOOSE\_DIR}$\DC{}. If this is set, %
\CD{}$\\{choose}(\,)$\DC{}
will select directories instead of files.
\medskip You may restrict the files presented for choosing by passing a pointer
to
the following structure for the \CD{}$\\{constraint}$\DC{} argument:
\Y\P $\&{typedef}\ \&{struct}\ \{\1$\6
$\&{short}\ \\{numTypes};$\5
\C{ Number of legitimate file types }\6
$\\{SFTypeList}\ \\{types};$\5
\C{ The types, like 'TEXT' }\2\6
$\}\ \\{sa\_constr\_file};$\par
\fi

\M51. \CD{}$\\{select}(\,)$\DC{} will give boring results. File descriptors are
{\it always} considered
ready to read or write, and {\it never} give exceptions.

\fi

\M52. \CD{}$\\{ioctl}(\,)$\DC{} and \CD{}$\\{fcntl}(\,)$\DC{} don't support
manipulating the blocking state of a file
descriptor or reading the number of bytes available for reading, but will
accept
lots of other requests---Check with your trusty MPW C documentation.

\fi

\N53. 4 Routines specific to the file system. In this section, you'll meet lots
of good
old friends.

\fi

\M54. \CD{}$\&{int}\ \\{stat}(\&{const}\ \&{char}\ {*}\\{path},\;\&{struct}\ %
\\{stat}\ {*}\\{buf})$\DC{} returns information about a file.
\CD{}$\&{struct}\ \\{stat}$\DC{} is defined as follows:
\Y\P $\&{struct}\ \\{stat}\ \{\1$\6
$\\{dev\_t}\ \\{st\_dev};$\5
\C{ Volume reference number of file  }\6
$\\{ino\_t}\ \\{st\_ino};$\5
\C{ File or directory ID         }\6
$\\{u\_short}\ \\{st\_mode};$\5
\C{ Type and permission of file  }\6
$\&{short}\ \\{st\_nlink};$\5
\C{ Always 1     }\6
$\&{short}\ \\{st\_uid};$\5
\C{ Set to 0     }\6
$\&{short}\ \\{st\_gid};$\5
\C{ Set to 0     }\6
$\\{dev\_t}\ \\{st\_rdev};$\5
\C{ Set to 0     }\6
$\\{off\_t}\ \\{st\_size};$\6
$\\{time\_t}\ \\{st\_atime};$\5
\C{ Set to $\\{st\_mtime}$  }\6
$\\{time\_t}\ \\{st\_mtime};$\6
$\\{time\_t}\ \\{st\_ctime};$\6
$\&{long}\ \\{st\_blksize};$\6
$\&{long}\ \\{st\_blocks};$\2\6
$\};$\par
\fi

\M55. \CD{}$\\{st\_mode}$\DC{} is composed of a file type and of file
permissions. The file type
may be one of the following:
\medskip\plaintwocol{
\CD{}$\\{S\_IFREG}$\DC{}&A regular file.\cr
\CD{}$\\{S\_IFDIR}$\DC{}&A directory.\cr
\CD{}$\\{S\_IFLNK}$\DC{}&A finder alias file.\cr
\CD{}$\\{S\_IFCHR}$\DC{}&A console file under MPW or SIOW.\cr
\CD{}$\\{S\_IFSOCK}$\DC{}&A file representing a UNIX domain socket.\cr
}
\medskip Permissions consist of an octal digit repeated three times. The three
bits
in the digit have the following meaning:
\medskip\plaintwocol{
\CD{}$\O{4}$\DC{}&File can be read.\cr
\CD{}$\O{2}$\DC{}&File can be written.\cr
\CD{}$\O{1}$\DC{}&File can be executed, i.e., its type is `APPL', `MPST' or
`TEXT'\cr
}

\fi

\M56. \CD{}$\&{int}\ \\{lstat}(\&{const}\ \&{char}\ {*}\\{path},\;\&{struct}\ %
\\{stat}\ {*}\\{buf})$\DC{} works just like \CD{}$\\{stat}(\,)$\DC{}, but if %
\CD{}$\\{path}$\DC{}
is a symbolic link, \CD{}$\\{lstat}(\,)$\DC{} will return information about the
link and not about
the file it points to.

\fi

\M57. \CD{}$\&{int}\ \\{fstat}(\&{int}\ \\{fd},\;\&{struct}\ \\{stat}\ {*}%
\\{buf})$\DC{} is the equivalent of \CD{}$\\{stat}(\,)$\DC{} for descriptors
representing open files. While it is legal to call \CD{}$\\{fstat}(\,)$\DC{}
for sockets, the
information returned is not really interesting. The file type in \CD{}$\\{st%
\_mode}$\DC{} will be
\CD{}$\\{S\_IFSOCK}$\DC{} for sockets.

\fi

\M58. \CD{}$\&{int}\ \\{isatty}(\&{int}\ \\{fd})$\DC{} returns \CD{}$\O{1}$%
\DC{} if \CD{}$\\{fd}$\DC{} represents a terminal (i.e. is connected
to \.{"Dev:StdIn"} and the like), \CD{}$\O{0}$\DC{} otherwise.

\fi

\M59. \CD{}$\&{long}\ \\{lseek}($ $\&{int}$ $,\;$ $\&{long}$ $,\;$ $\&{int}$
$)$\DC{} works the same as the \.{MPW} routine, and will
return \CD{}$\\{ESPIPE}$\DC{} if called for a socket.

\fi

\M60. \CD{}$\&{int}\ \\{remove}(\&{const}\ \&{char}\ {*}\\{filename})$\DC{}
removes the named file. If \CD{}$\\{filename}$\DC{} is a
symbolic link, the link will be removed and not the file.

\fi

\M61. \CD{}$\&{int}\ \\{unlink}(\&{const}\ \&{char}\ {*}\\{filename})$\DC{} is
identical to \CD{}$\\{remove}(\,)$\DC{}. Note that
on the Mac, \CD{}$\\{unlink}(\,)$\DC{} on open files behaves differently from %
\.{UNIX}.

\fi

\M62. \CD{}$\&{int}\ \\{rename}(\&{const}\ \&{char}\ {*}\\{oldname},\;\&{const}%
\ \&{char}\ {*}\\{newname})$\DC{} renames and/or moves a
file. \CD{}$\\{oldname}$\DC{} and \CD{}$\\{newname}$\DC{} must specify the same
volume, but as opposed to
the standard \.{MPW} routine, they may specify different folders.

\fi

\M63. \CD{}$\&{int}\ \\{open}(\&{const}\ \&{char}\ {*},\;\&{int}\ \\{flags})$%
\DC{} opens a named file. The \CD{}$\\{flags}$\DC{} consist
of one of the following modes:
\medskip\plaintwocol{
\CD{}$\\{O\_RDONLY}$\DC{}&Open for reading only.\cr
\CD{}$\\{WR\_ONLY}$\DC{}&Open for writing only.\cr
\CD{}$\\{O\_RDWR}$\DC{}&Open for reading and writing.\cr
}
\medskip Optionally combined with one or more of:
\medskip\plaintwocol{
\CD{}$\\{O\_APPEND}$\DC{}&The file pointer is set to the end of the file before
each write.\cr
\CD{}$\\{O\_RSRC}$\DC{}&Open resource fork.\cr
\CD{}$\\{O\_CREAT}$\DC{}&If the file does not exist, it is created.\cr
\CD{}$\\{O\_EXCL}$\DC{}&In combination with \CD{}$\\{O\_CREAT}$\DC{}, return an
error if file already exists.\cr
\CD{}$\\{O\_TRUNC}$\DC{}&If the file exists, its length is truncated to 0; the
mode is unchanged.\cr
\CD{}$\\{O\_ALIAS}$\DC{}&If the named file is a symbolic link, open the link,
not the file it points
to (This is most likely an incredibly bad idea).\cr
}

\fi

\M64. \CD{}$\&{int}\ \\{creat}(\&{const}\ \&{char}\ {*}\\{name})$\DC{} is
identical to \CD{}$\\{open}(\\{name},\;$$\\{O\_WRONLY}+\\{O\_TRUNC}+\\{O%
\_CREAT})$\DC{}.
If the file didn't exist before, \.{GUSI} determines its file type and creator
of the
according to rules outlined in the section ``Resources'' below.

\fi

\M65. \CD{}$\&{int}\ \\{faccess}(\&{const}\ \&{char}\ {*}\\{filename},\;%
\&{unsigned}\ \&{int}\ \\{cmd},\;\&{long}\ {*}\\{arg})$\DC{} works the same
as the corresponding \.{MPW} routine, but respects calls to \CD{}$\\{chdir}(%
\,)$\DC{} for partial
filenames.

\fi

\M66. \CD{}$\&{void}\ \\{fgetfileinfo}(\&{char}\ {*}\\{filename},\;\&{unsigned}%
\ \&{long}\ {*}\\{newcreator},\;\&{unsigned}\ \&{long}\ {*}\\{newtype})$\DC{}
returns the file type and creator of a file.

\fi

\M67. \CD{}$\&{void}\ \\{fsetfileinfo}(\&{char}\ {*}\\{filename},\;\&{unsigned}%
\ \&{long}\ \\{newcreator},\;\&{unsigned}\ \&{long}\ \\{newtype})$\DC{}
sets the file type and creator of a file to the given values.

\fi

\M68. \CD{}$\&{int}\ \\{symlink}(\&{const}\ \&{char}\ {*}\\{linkto},\;\&{const}%
\ \&{char}\ {*}\\{linkname})$\DC{} creates a file named \CD{}$\\{linkname}$%
\DC{} that
contains an alias resource pointing to \CD{}$\\{linkto}$\DC{}. The created file
should be
indistinguishible from an alias file created by the System 7 Finder. Note that
aliases bear only superficial similiarities to \.{UNIX} symbolic links,
especially
once you start renaming files.

\fi

\M69. \CD{}$\&{int}\ \\{readlink}(\&{const}\ \&{char}\ {*}\\{path},\;\&{char}\
{*}\\{buf},\;\&{int}\ \\{bufsiz})$\DC{} returns in \CD{}$\\{buf}$\DC{} the name
of the
file that \CD{}$\\{path}$\DC{} points to.

\fi

\M70. \CD{}$\&{int}\ \\{mkdir}(\&{const}\ \&{char}\ {*}\\{path})$\DC{} creates
a new directory.

\fi

\M71. \CD{}$\&{int}\ \\{rmdir}(\&{const}\ \&{char}\ {*}\\{path})$\DC{} deletes
an empty directory.

\fi

\M72. \CD{}$\&{int}\ \\{chdir}(\&{const}\ \&{char}\ {*}\\{path})$\DC{} makes
all future partial pathnames relative to this
directory.

\fi

\M73. \CD{}$\&{char}$ ${{*}}\\{getcwd}$ $($ $\&{const}\ \&{char}\ {{*}}\\{buf},%
\;\ \&{int}$ $\\{size}$ $)$\DC{} returns a pointer to the current directory
pathname. If \CD{}$\\{buf}$\DC{} is \CD{}$\\{NULL}$\DC{}, \CD{}$\\{size}$\DC{}
bytes will be allocated using \CD{}$\\{malloc}(\,)$\DC{}.
\medskip
Error codes:
\medskip\plaintwocol{
\CD{}$\\{ENAMETOOLONG}$\DC{}&The pathname of the current directory is greater
than \CD{}$\\{size}$\DC{}.\cr
\CD{}$\\{ENOMEM}$\DC{}&\CD{}$\\{buf}$\DC{} was \CD{}$\\{NULL}$\DC{} and \CD{}$%
\\{malloc}(\,)$\DC{} failed.\cr
}

\fi

\M74. A number of calls facilitate scanning directories. Directory entries are
represented by
following structure:
\Y\P $\&{struct}\ \\{dirent}\ \{\1$\6
$\\{u\_long}\ \\{d\_fileno};$\5
\C{ file number of entry }\6
$\\{u\_short}\ \\{d\_reclen};$\5
\C{ length of this record }\6
$\\{u\_short}\ \\{d\_namlen};$\5
\C{ length of string in $\\{d\_name}$ }\6
\8$\#{\let\\=\bf \\{define}}$\1{} $\\{MAXNAMLEN}\O{255}$\2\6
$\&{char}\ \\{d\_name}[\\{MAXNAMLEN}+\O{1}];$\5
\C{ name must be no longer than this }\2\6
$\};$\par
\fi

\M75. \CD{}$\\{DIR}$ ${{*}}\\{opendir}$ $($ $\&{const}\ \&{char}$ ${{*}}%
\\{dirname}$ $)$\DC{} opens a directory stream and returns a pointer or \CD{}$%
\\{NULL}$\DC{}
if the call failed.

\fi

\M76. \CD{}$\&{struct}\ \\{dirent}$ ${{*}}\\{readdir}(\\{DIR}{*}\\{dirp})$\DC{}
returns the next entry from the directory or \CD{}$\\{NULL}$\DC{}
if all entries have been processed.

\fi

\M77. \CD{}$\&{long}\ \\{telldir}($ $\&{const}$ $\\{DIR}$ ${{*}}\\{dirp}$ $)$%
\DC{} returns the position in the directory.

\fi

\M78. \CD{}$\&{void}\ \\{seekdir}(\\{DIR}\ {{*}}\\{dirp},\;\&{long}\ \\{loc})$%
\DC{} changes the position.

\fi

\M79. \CD{}$\&{void}\ \\{rewinddir}($ $\\{DIR}$ ${{*}}\\{dirp}$ $)$\DC{}
restarts a scan at the beginning.

\fi

\M80. \CD{}$\&{int}\ \\{closedir}($ $\\{DIR}$ ${{*}}\\{dirp}$ $)$\DC{} closes
the directory stream.

\fi

\M81. \CD{}$\&{int}\ \\{scandir}(\&{const}\ \&{char}\ {*}\\{path},\;\&{struct}\
\\{dirent}\ {*}{*}{*}\\{entries},\;\&{int}\ ({{*}}\\{want})(\&{struct}\ %
\\{dirent}\ {*}),\;$ $\&{int}$ $({{*}}\\{sort})$ $($ $\&{const}\ \&{void}$
${*}$ $,\;$ $\&{const}\ \&{void}$ ${*}$ $)$ $)$\DC{} scans a whole directory at
once and returns
a possibly sorted list of entries. If \CD{}$\\{want}$\DC{} is not \CD{}$%
\\{NULL}$\DC{}, only entries for which \CD{}$\\{want}$\DC{}
returns 1 are returned. If \CD{}$\\{sort}$\DC{} is not \CD{}$\\{NULL}$\DC{},
the list is sorted using \CD{}$\\{qsort}(\,)$\DC{} with
sort as a comparison function. If sort is \CD{}$\\{NULL}$\DC{}, the list will
be sorted alphabetically on
a Mac, but not necessarily on other machines.

\fi

\M82. \CD{}$\&{int}\ \\{truncate}(\&{const}\ \&{char}\ {*}\\{path},\;\\{off\_t}%
\ \\{length})$\DC{} causes a file to have a size equal to \CD{}$\\{length}$%
\DC{}
bytes, shortening it or extending it with zero bytes as necessary.

\fi

\M83. \CD{}$\&{int}\ \\{ftruncate}(\&{int}\ \\{fd},\;\\{off\_t}\ \\{length})$%
\DC{} does the same thing with an open file.

\fi

\N84. 2 Unix domain sockets. This domain is quite regular and supports all
calls that
work on any domain, except for out-of-band data.

\fi

\N85. 4 Differences to generic behavior.

\fi

\M86. Addresses are file system pathnames. \.{GUSI} complies to the
Unix implementation in that it doesn't require the name to be terminated by a
zero.
Names that are generated by \.{GUSI}, however, will always be zero terminated
(but
the zero won't be included in the count).
\Y\P $\&{struct}\ \\{sockaddr\_un}\ \{\1$\6
$\&{short}\ \\{sun\_family};$\5
\C{ Always $\\{AF\_UNIX}$   }\6
$\&{char}\ \\{sun\_path}[\O{108}];$\5
\C{ A pathname to a file }\2\6
$\};$\par
\fi

\M87. \CD{}$\\{choose}(\,)$\DC{} works both for existing and new addresses, and
no restriction
is possible (or necessary).

\fi

\N88. 2 Appletalk sockets. Currently, only stream sockets (including
out-of-band data)
are supported.

\fi

\N89. 4 Differences to generic behavior.

\fi

\M90. Two classes of addresses are supported for AppleTalk. The main address
type
specifies numeric addresses.
\Y\P $\&{struct}\ \\{sockaddr\_atlk}\ \{\1$\6
$\&{short}\ \\{family};$\5
\C{ Always $\\{AF\_APPLETALK}$      }\6
$\\{AddrBlock}\ \\{addr};$\5
\C{ The numeric AppleTalk socket address }\2\6
$\};$\par
\fi

\M91. For \CD{}$\\{bind}(\,)$\DC{} and \CD{}$\\{connect}(\,)$\DC{}, however,
you are also allowed to specify symbolic
addresses. \CD{}$\\{bind}(\,)$\DC{} registers an NBP address, and \CD{}$%
\\{connect}(\,)$\DC{} performs an NBP
lookup. Registered NBP adresses are automatically released when the socket is
closed. No call ever {\it returns} a symbolic address.
\Y\P $\&{struct}\ \\{sockaddr\_atlk\_sym}\ \{\1$\6
$\&{short}\ \\{family};$\5
\C{ Always $\\{ATALK\_SYMADDR}$  }\6
$\\{EntityName}\ \\{name};$\5
\C{ The symbolic NBP address }\2\6
$\};$\par
\fi

\M92. \CD{}$\\{choose}(\,)$\DC{} currently only works for existing sockets. The
peer must have registered
a symbolic address. To restrict the choice of addresses presented, pass a
pointer
to the following structure for the \CD{}$\\{constraint}$\DC{} argument:
\Y\P $\&{typedef}\ \&{struct}\ \{\1$\6
$\&{short}\ \\{numTypes};$\5
\C{ Number of allowed types }\6
$\\{NLType}\ \\{types};$\5
\C{ List of types }\2\6
$\}\ \\{sa\_constr\_atlk};$\par
\fi

\N93. 2 PPC sockets. These provide authenticated stream sockets without
out-of-band
data.

\fi

\N94. 4 Differences to generic behavior.

\fi

\M95. PPC socket addresses have the following format:
\Y\P $\&{struct}\ \\{sockaddr\_ppc}\ \{\1$\6
$\&{short}\ \\{family};$\5
\C{ Always $\\{AF\_PPC}$        }\6
$\\{LocationNameRec}\ \\{location};$\5
\C{ Check your trusty Inside Macintosh }\6
$\\{PPCPortRec}\ \\{port};$\2\6
$\};$\par
\fi

\M96. \CD{}$\\{choose}(\,)$\DC{} currently only works for existing sockets. To
restrict the choice of
addresses presented, pass a pointer to the following structure for the \CD{}$%
\\{constraint}$\DC{}
argument:
\Y\P $\&{typedef}\ \&{struct}\ \{\1$\6
$\&{short}\ \\{flags};$\6
$\\{Str32}\ \\{nbpType};$\6
$\\{PPCPortRec}\ \\{match};$\2\6
$\}\ \\{sa\_constr\_ppc};$\par
\fi

\M97. \CD{}$\\{flags}$\DC{} is obtained by or'ing one or several of the
following constants:
\medskip\plaintwocol{
\CD{}$\\{PPC\_CON\_NEWSTYLE}$\DC{}&Always required for compatibility reasons.%
\cr
\CD{}$\\{PPC\_CON\_MATCH\_NBP}$\DC{}&Only display machines that have registered
an entity of type \CD{}$\\{nbpType}$\DC{}.\cr
\CD{}$\\{PPC\_CON\_MATCH\_NAME}$\DC{}&Only display ports whose name matches %
\CD{}$\\{match}.\\{name}$\DC{}.\cr
\CD{}$\\{PPC\_CON\_MATCH\_TYPE}$\DC{}&Only display ports whose type matches %
\CD{}$\\{match}.\|u.\\{portType}$\DC{}.\cr
}
\medskip
\CD{}$\\{nbpType}$\DC{} specifies the machines to be displayed, as explained
above. \CD{}$\\{match}$\DC{} contains the name
and/or type to match against.

\fi

\M98. \CD{}$\\{connect}(\,)$\DC{} will block even if the socket is nonblocking.
In practice, however,
delays are likely to be quite short, as it never has to block on a higher level
protocol and the PPC ToolBox will automatically establish the connection.

\fi

\N99. 2 Internet sockets. These are the real thing for real programmers.
Out-of-band
data only works for sending. Both stream (TCP) and datagram (UDP) sockets are
supported.

\fi

\N100. 4 Differences to generic behavior.

\fi

\M101. Internet socket addresses have the following format:
\Y\P $\&{struct}\ \\{in\_addr}\ \{\1$\6
$\\{u\_long}\ \\{s\_addr};$\2\6
$\};$\7
$\&{struct}\ \\{sockaddr\_in}\ \{\1$\6
$\\{u\_char}\ \\{sin\_len};$\5
\C{ Ignored }\6
$\\{u\_char}\ \\{sin\_family};$\5
\C{ Always $\\{AF\_INET}$ }\6
$\\{u\_short}\ \\{sin\_port};$\5
\C{ Port number }\6
$\&{struct}\ \\{in\_addr}\ \\{sin\_addr};$\5
\C{ Host ID }\6
$\&{char}\ \\{sin\_zero}[\O{8}];$\2\6
$\};$\par
\fi

\N102. 4 Routines specific to TCP/IP sockets. There are several routines to
convert
between numeric and symbolic addresses.

\fi

\M103. Hosts are represented by the following structure:
\Y\P $\&{struct}\ \\{hostent}\ \{\1$\6
$\&{char}\ {{*}}\\{h\_name};$\5
\C{ Official name of the host      }\6
$\&{char}\ {{*}}{{*}}\\{h\_aliases};$\5
\C{ A zero terminated array of alternate names for the host   }\6
$\&{int}\ \\{h\_addrtype};$\5
\C{ Always $\\{AF\_INET}$        }\6
$\&{int}\ \\{h\_length};$\5
\C{ The length, in bytes, of the address }\6
$\&{char}\ {{*}}{{*}}\\{h\_addr\_list};$\5
\C{ A zero terminated array of network addresses for the host }\2\6
$\};$\par
\fi

\M104. \CD{}$\&{struct}\ \\{hostent}$ ${{*}}\\{gethostbyname}$ $($ $\&{char}$
${{*}}\\{name}$ $)$\DC{} returns an entry for the host
with the given \CD{}$\\{name}$\DC{} or \CD{}$\\{NULL}$\DC{} if a host with this
name can't be found.

\fi

\M105. \CD{}$\&{struct}\ \\{hostent}$ ${{*}}\\{gethostbyaddr}$ $($ $\&{const}\ %
\&{char}\ {{*}}\\{addrP},\;\ \&{int}$ $,\;$ $\&{int}$ $)$\DC{} returns an
entry for the host with the given address or \CD{}$\\{NULL}$\DC{} if a host
with this name
can't be found. \CD{}$\\{addrP}$\DC{} in fact has to be a \CD{}$\&{struct}\ %
\\{in\_addr}$ ${*}$\DC{}. The last two
parameters are ignored.

\fi

\M106. \CD{}$\&{char}$ ${{*}}\\{inet\_ntoa}$ $($ $\&{struct}\ \\{in\_addr}$ $%
\\{inaddr}$ $)$\DC{} converts an internet address into
the usual numeric string representation (e.g., 0x8184023C is converted to
"129.132.2.60")

\fi

\M107. \CD{}$\&{struct}\ \\{in\_addr}\ \\{inet\_addr}(\&{char}\ {*}%
\\{address})$\DC{} converts a numeric string into an
internet address (If \CD{}$\|x$\DC{} is a valid address, \CD{}$\\{inet\_addr}(%
\\{inet\_ntoa}(\|x))\S\|x$\DC{}).

\fi

\M108. \CD{}$\&{int}\ \\{gethostname}(\&{char}\ {*}\\{machname},\;\&{long}\ %
\\{buflen})$\DC{} gets our name into \CD{}$\\{buffer}$\DC{}.

\fi

\M109. Services are represented by the following data structure:
\Y\P $\&{struct}\ \\{servent}\ \{\1$\6
$\&{char}\ {{*}}\\{s\_name};$\5
\C{ official service name }\6
$\&{char}\ {{*}}{{*}}\\{s\_aliases};$\5
\C{ alias list  }\6
$\&{int}\ \\{s\_port};$\5
\C{ port number }\6
$\&{char}\ {{*}}\\{s\_proto};$\5
\C{ protocol to use ("tcp" or "udp") }\2\6
$\};$\par
\fi

\M110. \CD{}$\&{void}\ \\{setservent}(\&{int}\ \\{stayopen})$\DC{} rewinds the
file of services. If \CD{}$\\{stayopen}$\DC{} is
set, the file will remain open until \CD{}$\\{endservent}(\,)$\DC{} is called,
else it will be
closed after the next call to \CD{}$\\{getservbyname}(\,)$\DC{} or \CD{}$%
\\{getservbyport}(\,)$\DC{}.

\fi

\M111. \CD{}$\&{void}\ \\{endservent}()$\DC{} closes the file of services.

\fi

\M112. \CD{}$\&{struct}\ \\{servent}$ ${{*}}\\{getservent}(\,)$\DC{} returns
the next service from the file of services,
opening the file first if necessary. If the file is not found (%
\.{/etc/services} in
the preferences folder), a small built-in list is consulted. If there are no
more services,
\CD{}$\\{getservent}(\,)$\DC{} returns \CD{}$\\{NULL}$\DC{}.

\fi

\M113. \CD{}$\&{struct}\ \\{servent}$ ${{*}}\\{getservbyname}$ $($ $\&{const}\ %
\&{char}\ {{*}}\\{name},\;\ \&{const}\ \&{char}$ ${{*}}\\{proto}$ $)$\DC{}
finds a named
service by calling \CD{}$\\{getservent}(\,)$\DC{} until the protocol matches %
\CD{}$\\{proto}$\DC{} and either the name or
one of the aliases matches \CD{}$\\{name}$\DC{}.

\fi

\M114. \CD{}$\&{struct}\ \\{servent}$ ${{*}}\\{getservbyport}$ $($ $\&{int}\ %
\\{port},\;\ \&{const}\ \&{char}$ ${{*}}\\{proto}$ $)$\DC{} finds a
service by calling \CD{}$\\{getservent}(\,)$\DC{} until the protocol matches %
\CD{}$\\{proto}$\DC{} and the
port matches \CD{}$\\{port}$\DC{}.

\fi

\M115. Protocols are represented by the following data structure:
\Y\P $\&{struct}\ \\{protoent}\ \{\1$\6
$\&{char}\ {{*}}\\{p\_name};$\5
\C{ official protocol name }\6
$\&{char}\ {{*}}{{*}}\\{p\_aliases};$\5
\C{ alias list (always $\\{NULL}$ for \.{GUSI})}\6
$\&{int}\ \\{p\_proto};$\5
\C{ protocol number }\2\6
$\};$\par
\fi

\M116. \CD{}$\&{struct}\ \\{protoent}$ ${{*}}\\{getprotobyname}$ $($ $\&{char}$
${{*}}\\{name}$ $)$\DC{} finds a named protocol. This
call is rather unexciting.

\fi

\N117. 2 PAP sockets. PAP, the AppleTalk Printer Access Protocol is a protocol
which is
almost exclusively used to access networked printers. The current
implementation of
PAP in \.{GUSI} is quite narrow in that it only implements the workstation side
of
PAP and only in communication to the currently selected LaserWriter. It is also
doomed, as it depends on Apple system resources that probably won't be
supported
anymore in Apple's forthcoming new printing architecture, but if there is
enough
interest, the current implementation is probably going to be replaced until
then.

\fi

\N118. 4 Routines specific to PAP sockets. While PAP sockets behave in most
respects like
other sockets, they can currently not be created with the \CD{}$\\{socket}(\,)$%
\DC{} call, but are
opened with \CD{}$\\{open}(\,)$\DC{}.

\fi

\M119. \CD{}$\&{int}\ \\{open}($ $\.{"Dev:Printer"}$ $,\;$ $\&{int}$ $%
\\{flags}$ $)$\DC{} opens a connection to the last selected
LaserWriter. \CD{}$\\{flags}$\DC{} is currently ignored.

\fi

\M120. Communication with LaserWriters is somewhat strange. The three main uses
of PAP
sockets are probably interactive sessions, queries, and downloads, which will
be
discussed in the following sections. As in all other socket families, \.{GUSI}
does
no filtering of the transmitted data, which means that lines sent by the
LaserWriter
will be separated by linefeeds (ASCII 10) rather than carriage returns (ASCII
13),
which are used for this purpose in most other Mac contexts. For data you {\it
send}, it
doesn't matter which one you use.

\fi

\M121. You start an {\it interactive session} by sending a line \.{"executive"}
after
opening the socket. This will put lots of LaserWriters (certainly all
manufactured
by Apple, but probably not a Linotronic) into interactive mode. If you want to,
you
can now play terminal emulator and use your LaserWriter as an expensive desk
calculator.

\fi

\M122. A {\it query} is some PostScript code you send to a LaserWriter that you
expect
to be answered. This is quite straightforward, except that LaserWriters don't
seem
to answer until you have indicated to them that no more data from you will be
coming.
Therefore, you have to call \CD{}$\\{shutdown}(\|s,\;$$\O{1})$\DC{} to shut the
socket down for writing after
you have written your query and before you try to read the answer. The
following
code demonstrates how to send a query to the printer:

\Y\P $\&{int}\ \|s\leftarrow\\{open}(\.{"Dev:Printer"},\;$\39$\\{O\_RDWR});$\7
$\\{write}(\|s,\;$\39$\.{"FontDirectory\ /Gorilla-SemiBold\ exch\ known..."},%
\;$\39$\\{len});$\7
\C{ We won't write any more }\6
$\\{shutdown}(\|s,\;$\39$\O{1});$\7
$\&{while}\ (\\{read}(\|s,\;$\39$\\{buf},\;$\39$\\{len})>\O{0})$\1\6
$\\{do\_something}(\,);$\2\7
$\\{close}(\|s);$\par
\fi

\M123. If you want to simply {\it download} a file, you can also ignore the
LaserWriter's
response and simply close the socket after downloading.

\fi

\N124. 2 Miscellaneous.

\fi

\N125. 4 BSD memory routines.

\fi

\M126. \CD{}$\&{void}\ \\{bzero}(\&{void}\ {*}\\{from},\;\&{int}\ \\{len})$%
\DC{} zeroes \CD{}$\\{len}$\DC{} bytes, starting at \CD{}$\\{from}$\DC{}.

\fi

\M127. \CD{}$\\{bfill}($ $\&{void}\ {{*}}\\{from},\;\ \&{int}\ \\{len},\;\ %
\&{int}$ $\|x$ $)$\DC{} fills \CD{}$\\{len}$\DC{} bytes, starting at \CD{}$%
\\{from}$\DC{} with
\CD{}$\|x$\DC{}.

\fi

\M128. \CD{}$\&{void}\ \\{bcopy}(\&{void}\ {*}\\{from},\;\&{void}\ {*}\\{to},\;%
\&{int}\ \\{len})$\DC{} copies \CD{}$\\{len}$\DC{} bytes from \CD{}$\\{from}$%
\DC{} to
\CD{}$\\{to}$\DC{}.

\fi

\M129. \CD{}$\&{int}\ \\{bcmp}(\&{void}\ {*}\\{s1},\;\&{void}\ {*}\\{s2},\;%
\&{int}\ \\{len})$\DC{} compares \CD{}$\\{len}$\DC{} bytes at \CD{}$\\{s1}$%
\DC{} against
\CD{}$\\{len}$\DC{} bytes at \CD{}$\\{s2}$\DC{}, returning zero if the two
areas are equal, nonzero otherwise.

\fi

\N130. 4 Blocking calls. Since the Macintosh doesn't have preemptive task
switching, it
is important that other applications get a chance to run during blocking calls.
This
section discusses the mechanism \.{GUSI} uses for that purpose.

\fi

\M131. While a routine is waiting for a blocking call to terminate, it
repeatedly calls a
spin routine with the following parameters:
\Y\P $\&{typedef}\ $ $\&{enum}\ \\{spin\_msg}\ \{\1$ $\\{SP\_MISC}$ $,\;$\5
\C{ some weird thing, usually just return immediately if you get this }\6
$\\{SP\_SELECT}$ $,\;$\5
\C{ in a select call }\6
$\\{SP\_NAME}$ $,\;$\5
\C{ getting a host by name }\6
$\\{SP\_ADDR}$ $,\;$\5
\C{ getting a host by address }\6
$\\{SP\_STREAM\_READ}$ $,\;$\5
\C{ Stream read call }\6
$\\{SP\_STREAM\_WRITE}$ $,\;$\5
\C{ Stream write call }\6
$\\{SP\_DGRAM\_READ}$ $,\;$\5
\C{ Datagram read call }\6
$\\{SP\_DGRAM\_WRITE}$ $,\;$\5
\C{ Datagram write call }\6
$\\{SP\_SLEEP}$ $,\;$\5
\C{ sleeping, passes ticks left to sleep }\6
$\\{SP\_AUTO\_SPIN}$\5
\C{ Automatically spinning, passes spin count }\6
$\}$ $\\{spin\_msg};$\7
$\&{typedef}\ $ $\&{int}$ $({{*}}\\{GUSISpinFn})$ $($ $\\{spin\_msg}\ \\{msg}$
$,\;$ $\&{long}$ $\\{param}$ $)$ $;$\par
\fi

\M132. You can modify the spin routine with the following calls:
\Y\P $\&{int}\ \\{GUSISetSpin}(\\{GUSISpinFn}\ \\{routine})$\1$;$\2\7
$\\{GUSISpinFn}\ \\{GUSIGetSpin}($ $\&{void}$ $)$ $;$\par
\fi

\M133. Usually, however, the default spin routine will do what you want: It
spins a
cursor and occasionally calls \CD{}$\\{GetNextEvent}(\,)$\DC{} or \CD{}$%
\\{WaitNextEvent}(\,)$\DC{}. By default,
only mouse down and suspend/resume events are handled, but you can change that
by passing your own \CD{}$\\{GUSIEvtTable}$\DC{} to \CD{}$\\{GUSISetEvents}(%
\,)$\DC{}.
\Y\P $\&{int}\ \\{GUSISetEvents}(\\{GUSIEvtTable}\ \\{table})$\1$;$\2\7
$\\{GUSIEvtHandler}\ {{*}}\\{GUSIGetEvents}(\&{void});$\par
\fi

\M134. A \CD{}$\\{GUSIEvtTable}$\DC{} is a table of \CD{}$\\{GUSIEvtHandlers}$%
\DC{}, indexed by event code. Presence
of a non-nil entry in the table will cause that event class to be allowed for
\CD{}$\\{GetNextEvent}(\,)$\DC{} or \CD{}$\\{WaitNextEvent}(\,)$\DC{}. \.{GUSI}
includes one event table to
be used with the \.{SIOW} library.
\Y\P $\&{typedef}\ \&{void}\ ({{*}}\\{GUSIEvtHandler})(\\{EventRecord}{*}%
\\{ev});$\6
$\&{typedef}\ \\{GUSIEvtHandler}\ \\{GUSIEvtTable}[\O{24}];$\7
$\&{extern}\ \\{GUSIEvtHandler}\ \\{GUSISIOWEvents}[];$\par
\fi

\N135. 4 Resources. A few \.{GUSI} routines (currently primarily choose()) need
resources
to work correctly. These are added if you Rez your program with \.{GUSI.r}. On
startup, \.{GUSI} also looks for a {\it preference} resource with type
\.{`GU$\Sigma$I'} and ID \CD{}$\\{GUSIRsrcID}$\DC{}, which is currently defined
as follows:
\Y\P\8$\#{\let\\=\bf \\{ifndef}}$\1{} $\\{GUSI\_PREF\_VERSION}$\2\6
\8$\#{\let\\=\bf \\{define}}$\1{} $\\{GUSI\_PREF\_VERSION}$'$\O{0102}$'\2\6
\8$\#{\let\\=\bf \\{endif}}$\1{} \2\7
$\hbox{{\bf type} `\.{GU$\Sigma$I}' }$\1 $\{\1$\6
$\\{literal}\ \\{longint}\ \\{text}\leftarrow$'$\\{TEXT}$'$;$\5
\C{ Type for creat'ed files     }\6
$\\{literal}\ \\{longint}\ \\{mpw}\leftarrow$'$\\{MPS}$'$;$\5
\C{ Creator for creat'ed files     }\6
$\\{byte}\ \\{noAutoSpin},\;\ \\{autoSpin};$\5
\C{ Automatically spin cursor ?   }\6
\8$\#{\let\\=\bf \&{if}\ }$\1{} $\\{GUSI\_PREF\_VERSION}\G$'$\O{0110}$'\2\6
$\\{boolean}\ \\{useChdir},\;\ \\{dontUseChdir};$\5
\C{ Use chdir() ?       }\6
$\\{boolean}\ \\{approxStat},\;\ \\{accurateStat};$\5
\C{ statbuf.st\_nlink = \# of subdirectories ? }\6
$\\{boolean}\ \\{noTCPDaemon},\;\ \\{isTCPDaemon};$\5
\C{ Inetd client ?       }\6
$\\{boolean}\ \\{noUDPDaemon},\;\ \\{isUDPDaemon};$\6
$\\{fill}\ \\{bit}[\O{4}];$\6
$\\{literal}\ \\{longint}\leftarrow\\{GUSI\_PREF\_VERSION};$\6
\8$\#{\let\\=\bf \&{if}\ }$\1{} $\\{GUSI\_PREF\_VERSION}\G$'$\O{0120}$'\2\7
$\\{integer}\leftarrow\hbox{\$\$}\\{Countof}(\\{SuffixArray});$\7
$\\{wide}\ \\{array}$ $\\{SuffixArray}$ $\{\1$ $\\{literal}\ \\{longint};$\5
\C{ Suffix of file }\6
$\\{literal}\ \\{longint};$\5
\C{ Type for file }\6
$\\{literal}\ \\{longint};$\5
\C{ Creator for file }\6
$\}$ $;$\6
\8$\#{\let\\=\bf \\{endif}}$\1{} \2\6
\8$\#{\let\\=\bf \\{endif}}$\1{} \2\6
$\}$ $;$\par
\fi

\M136. To keep backwards compatible, the preference version is included, and
you are free to
use whatever version of the preferences you want by defining \CD{}$\\{GUSI%
\_PREF\_VERSION}$\DC{}.

\fi

\M137. The first two fields define the file type and creator, respectively, to
be used
for files created by \.{GUSI}. The type and creator of existing files will
never
be changed unless explicitely requested with fsetfileinfo(). The default is to
create text files (type `TEXT') owned by the \.{MPW Shell} (creator `MPS '). If
you
request a preference version of 1.2.0 and higher, you are also allowed to
specify
a list of suffixes that are given different types. An example of such a list
would be:
\Y\P $\{\1$' $\\{SYM}$' $,\;$' $\\{MPSY}$' $,\;$' $\\{sade}$' $\}$\par
\fi

\M138. The \CD{}$\\{autoSpin}$\DC{} value, if nonzero, makes \.{GUSI} call the
spin routine for every
call to \CD{}$\\{read}(\,)$\DC{}, \CD{}$\\{write}(\,)$\DC{}, \CD{}$\\{send}(%
\,)$\DC{}, or \CD{}$\\{recv}(\,)$\DC{}. This is useful for making
an I/O bound program MultiFinder friendly without having to insert explicit
calls
to \CD{}$\\{SpinCursor}(\,)$\DC{}. If you don't specify a preference resource, %
\CD{}$\\{autoSpin}$\DC{} is assumed
to be \CD{}$\O{1}$\DC{}. You may specify arbitrary values greater than one to
make your program
even friendlier; note, however, that this will hurt performance.

\fi

\M139. The \CD{}$\\{useChdir}$\DC{} flag tells \.{GUSI} whether you change
directories with the
toolbox calls \CD{}$\\{PBSetVol}(\,)$\DC{} or \CD{}$\\{PBHSetVol}(\,)$\DC{} or
with the \.{GUSI} call \CD{}$\\{chdir}(\,)$\DC{}.
The current directory will start with the directory your application resides in
or the current \.{MPW} directory, if you're running an \.{MPW} tool.
If \CD{}$\\{useChdir}$\DC{} is specified, the current directory will only
change with \CD{}$\\{chdir}(\,)$\DC{}
calls. If \CD{}$\\{dontUseChdir}$\DC{} is specified, the current directory will
change with
toolbox calls, until you call \CD{}$\\{chdir}(\,)$\DC{} the first time. This
behaviour is more
consistent with the standard \.{MPW} library, but has IMHO no other redeeming
value. If you don't specify a preference resource, \CD{}$\\{useChdir}$\DC{} is
assumed.

\fi

\M140. If \CD{}$\\{approxStat}$\DC{} is specified, \CD{}$\\{stat}(\,)$\DC{} and
\CD{}$\\{lstat}(\,)$\DC{} for directories return in
\CD{}$\\{st\_nlink}$\DC{} the number of {\it items} in the directory \CD{}${+}%
\O{2}$\DC{}. If \CD{}$\\{accurateStat}$\DC{} is
specified, they return the number of {\it subdirectories} in the directory. The
latter has probably the best chances of being compatible with some Unix
software,
but the former is often a sufficient upper bound, is much faster, and most
programs
don't care about this value anyway. If you don't specify a preference resource,
\CD{}$\\{approxStat}$\DC{} is assumed.

\fi

\M141. The \CD{}$\\{isTCPDaemon}$\DC{} and \CD{}$\\{isUDPDaemon}$\DC{} flags
turn \.{GUSI} programs into clients
for David Petersons \.{inetd}, as discussed below. If you don't specify a
preference
resource, \CD{}$\\{noTCPDaemon}$\DC{} and \CD{}$\\{noUDPDaemon}$\DC{} are
assumed.

\fi

\N142. = Advanced techniques. This section discusses a few techniques that
probably not
every user of \.{GUSI} needs.

\fi

\N143. 2 Writing daemons. David Peterson $<$david\AT!stealth.usc.edu$>$ has
written an
Internet daemon for the Macintosh. This is a program that listens on various
ports
for a connection, and if one arrives, launches a server program to handle it.
\.{GUSI} contains code that makes it extremely easy to interface with inetd:
All you
have to do is to set the \CD{}$\\{tcpDaemon}$\DC{} and/or the \CD{}$%
\\{udpDaemon}$\DC{} flag in the configuration
resource. \.{GUSI} and inetd will then conspire to have file descriptors 0, 1,
and 2
connected to the incoming socket. Therefore, all you have to do is to read and
write
from and to 0, 1, 2 (or stdin, stdout, and stderr, if you're using stdio).

inetd is available by anonymous ftp from the following locations:
\medskip\plaintwocol{
\.{usc.edu}&\.{pub/davidp}\cr
\.{nic.switch.ch}&\.{software/mac/src/mpw\_c}\cr
}



\fi

\N144. 2 FSSpec routines. If you need to do complicated things with the Mac
file system,
the normal \.{GUSI} routines are probably not sufficient, but you still might
want to use the internal mechanism \.{GUSI} uses. This mechanism is provided in
the header file \.{TFileSpec.h}, which defines both \CD{}$\|C$\DC{} and \CD{}$%
\|C\PP$\DC{} interfaces.

\fi

\N145. 2 Adding your own communication families. It is rather easy to add your
own socket
types to \.{GUSI}:
\medskip\onecollist{
Pick an unused number between 17 and \CD{}$\\{GUSI\_MAX\_DOMAINS}$\DC{} to use
for your address family.\cr
Include \.{GUSI\_P.h}.\cr
Write a subclass of \CD{}$\\{SocketDomain}$\DC{} and override \CD{}$\\{choose}(%
\,)$\DC{} and either \CD{}$\\{open}(\,)$\DC{} or
\CD{}$\\{socket}(\,)$\DC{}. If you override \CD{}$\\{open}(\,)$\DC{}, you have
to write your own routine to
create sockets of this type.\cr
Write a subclass of \CD{}$\\{Socket}$\DC{} and override whatever you want. If
you override
\CD{}$\\{recvfrom}(\,)$\DC{} and \CD{}$\\{sendto}(\,)$\DC{}, \CD{}$\\{read}(%
\,)$\DC{} and \CD{}$\\{write}(\,)$\DC{} are automatically defined.\cr
For more information, study the code in \.{GUSIDispatch.cp} and %
\.{GUSISocket.cp},
which implement the generic socket code. The easiest actual socket
implementation
to study is probably \.{GUSIUnix.cp}.\cr
}

\fi

\N146. = Known problems, words of warning. \medskip\onecollist{
\CD{}$\\{O\_NRESOLVE}$\DC{}, as introduced in the E.T.O \#8 Prerelease
libraries, is interpreted
the same way as \CD{}$\\{O\_ALIAS}$\DC{}, i.e. intermediate aliases are
silently resolved. On the
other hand, I can't think of a good reason why anybody would use \CD{}$\\{O%
\_NRESOLVE}$\DC{}.\cr
\CD{}$\\{getsockname}(\,)$\DC{} for TCP/IP sockets for which neither \CD{}$%
\\{bind}(\,)$\DC{} with a nonzero port
number nor \CD{}$\\{connect}(\,)$\DC{} or \CD{}$\\{listen}(\,)$\DC{} have been
called returns zero.\cr
\CD{}$\\{bind}(\,)$\DC{} for TCP/IP sockets doesn't check for duplicate port
numbers.\cr
}

\fi

\N147. = References. The following books might provide you with more
information about
various aspects of \.{GUSI}.

\medskip\bibliolist{
Appl85&Apple Computer, Inc., {\it Inside Macintosh Volume I--VI}, Addison
Wesley, 1985--91\cr
Appl88&Apple Computer, Inc., {\it Macintosh Programmer's Workshop C}, 1988\cr
Crow13&Aleister Crowley, {\it The Book of Lies}, 1913\cr
Holz91&David A.~Holzgang, {\it Programming the LaserWriter}, Addison-Wesley
1991\cr
LMKQ89&Samuel J.~Leffler, Marshall Kirk McKusick, Michael J.~Karels, John
S.~Quarterman, {\it The Design and Implementation of the 4.3BSD UNIX Operating
System}, Addison Wesley, 1989\cr
Stev90&W.~Richard Stevens, {\it UNIX Network Programming}, Prentice Hall,
1990\cr
Stev92&W.~Richard Stevens, {\it Advanced Programming in the UNIX Environment},
Prentice Hall,
1992\cr
Sun88&Sun Microsystems, Inc., {\it SunOS Reference Manual}, 1988\cr
}

\fi

\N148. = Index.
\fi


\inx
\:\\{accept}, 17, \[20], 48.
\:\\{accurateStat}, \[135], 140.
\:\\{addr}, \[20], \[21], \[90].
\:\\{AddrBlock}, 90.
\:\\{address}, \[107].
\:\\{addrlen}, \[20], \[21].
\:\\{addrP}, \[105].
\:\\{af}, \[13].
\:\\{AF\_APPLETALK}, 13, 90.
\:\\{AF\_INET}, 13, 101, 103.
\:\\{AF\_PPC}, 13, 95.
\:\\{AF\_UNIX}, 13, 86.
\:\\{approxStat}, \[135], 140.
\:\\{arg}, \[40], \[65].
\:\\{argp}, \[39].
\:\\{array}, 135.
\:\\{ATALK\_SYMADDR}, 91.
\:\\{autoSpin}, \[135], 138.
\:\\{bcmp}, \[129].
\:\\{bcopy}, \[128].
\:\\{bfill}, 127.
\:\\{bind}, 16, 17, \[18], 48, 91, 146.
\:\\{bit}, \[135].
\:\\{boolean}, 135.
\:\\{buf}, \[54], \[56], \[57], \[69], \[73], 122.
\:\\{buffer}, \[23], \[25], \[26], \[28], \[30], \[31], 108.
\:\\{buflen}, \[23], \[25], \[26], \[28], \[30], \[31], \[108].
\:\\{bufsiz}, \[69].
\:\\{byte}, 135.
\:\\{bzero}, \[126].
\:\\{caddr\_t}, 24, 27.
\:\\{chdir}, 1, 65, \[72], 139.
\:\\{choose}, 15, \[16], 18, 50, 87, 92, 96, 145.
\:\\{CHOOSE\_DEFAULT}, 16.
\:\\{CHOOSE\_DIR}, 50.
\:\\{CHOOSE\_NEW}, 16.
\:\\{close}, 12, \[14], 122.
\:\\{closedir}, \[80].
\:\\{cmd}, \[40], \[65].
\:\\{connect}, 16, 17, \[21], 48, 91, 98, 146.
\:\\{constraint}, \[16], 50, 92, 96.
\:\\{count}, \[24], \[29].
\:\\{Countof}, 135.
\:\\{creat}, \[64].
\:\\{d\_fileno}, \[74].
\:\\{d\_name}, \[74].
\:\\{d\_namlen}, \[74].
\:\\{d\_reclen}, \[74].
\:\\{define}, 74, 135.
\:\\{dev\_t}, 54.
\:\\{DIR}, 75, 76, 77, 78, 79, 80.
\:\\{dirent}, \[74], 76, 81.
\:\\{dirname}, 75.
\:\\{dirp}, 76, 77, \[78], 79, 80.
\:\\{do\_something}, 122.
\:\\{dom}, \[16].
\:\\{dontUseChdir}, \[135], 139.
\:\\{dup}, 36, \[43].
\:\\{dup2}, 36, \[44].
\:\\{EADDRINUSE}, 18.
\:\\{EADDRNOAVAIL}, 21.
\:\\{EAFNOSUPPORT}, 18, 21.
\:\\{EBADF}, 11, 34.
\:\\{ECONNREFUSED}, 21.
\:\\{EINPROGRESS}, 21.
\:\\{EINTR}, 11, 16.
\:\\{EINVAL}, 13, 16.
\:\\{EISCONN}, 21.
\:\\{EMFILE}, 13.
\:\\{ENAMETOOLONG}, 73.
\:\\{endif}, 135.
\:\\{endservent}, 110, \[111].
\:\\{ENOMEM}, 11, 73.
\:\\{ENOTCONN}, 11, 20.
\:\\{EntityName}, 91.
\:\\{entries}, \[81].
\:\\{EOPNOTSUPP}, 39, 40, 48.
\:\\{errno}, 11.
\:\\{ESPIPE}, 59.
\:\\{ev}, 134.
\:\\{EventRecord}, 134.
\:\\{EWOULDBLOCK}, 20, 23, 28.
\:\\{exceptfds}, \[34].
\:\\{exceptfs}, 34.
\:\\{F\_DUPFD}, 40.
\:\\{F\_GETFL}, 40.
\:\\{F\_SETFL}, 40.
\:\\{faccess}, \[65].
\:\\{family}, \[90], \[91], \[95].
\:\\{fcntl}, 36, \[40], 52.
\:\\{fd}, \[14], \[43], \[57], \[58], \[83].
\:\\{FD\_CLR}, 35.
\:\\{FD\_ISSET}, 35.
\:\\{FD\_SET}, 35.
\:\\{fd\_set}, 34.
\:\\{FD\_ZERO}, 35.
\:\\{fds}, 35.
\:\\{fgetfileinfo}, \[66].
\:\\{filename}, \[60], \[61], \[65], \[66], \[67].
\:\\{fill}, 135.
\:\\{FIONBIO}, 39.
\:\\{FIONREAD}, 39.
\:\\{flags}, \[16], \[25], \[26], \[27], \[30], \[31], \[32], \[63], \[96], 97,
119.
\:\\{FNDELAY}, 40.
\:\\{from}, \[26], 27, \[126], \[127], \[128].
\:\\{fromlen}, \[26], 27.
\:\\{fsetfileinfo}, \[67].
\:\\{FSSpec}, 7.
\:\\{fstat}, \[57].
\:\\{ftruncate}, \[83].
\:\\{getcwd}, 1, 73.
\:\\{gethostbyaddr}, 105.
\:\\{gethostbyname}, 104.
\:\\{gethostname}, \[108].
\:\\{GetNextEvent}, 133, 134.
\:\\{getpeername}, 36, \[38], 48.
\:\\{getprotobyname}, 116.
\:\\{getservbyname}, 110, 113.
\:\\{getservbyport}, 110, 114.
\:\\{getservent}, 112, 113, 114.
\:\\{getsockname}, 36, \[37], 48, 146.
\:\\{getsockopt}, 36, \[41], 48.
\:\\{GUSI\_MAX\_DOMAINS}, 145.
\:\\{GUSI\_PREF\_VERSION}, 135, 136.
\:\\{GUSIEvtHandler}, 133, \[134].
\:\\{GUSIEvtHandlers}, 134.
\:\\{GUSIEvtTable}, 133, \[134].
\:\\{GUSIGetEvents}, \[133].
\:\\{GUSIGetSpin}, \[132].
\:\\{GUSIRsrcID}, 135.
\:\\{GUSISetEvents}, \[133].
\:\\{GUSISetSpin}, \[132].
\:\\{GUSISIOWEvents}, \[134].
\:\\{GUSISpinFn}, 131, 132.
\:\\{h\_addr\_list}, \[103].
\:\\{h\_addrtype}, \[103].
\:\\{h\_aliases}, \[103].
\:\\{h\_length}, \[103].
\:\\{h\_name}, \[103].
\:\\{hostent}, \[103], 104, 105.
\:\\{ifndef}, 135.
\:\\{in\_addr}, \[101], 105, 106, 107.
\:\\{inaddr}, 106.
\:\\{inet\_addr}, \[107].
\:\\{inet\_ntoa}, 106, 107.
\:\\{InitCursor}, 8.
\:\\{InitDialogs}, 8.
\:\\{InitFonts}, 8.
\:\\{InitGraf}, 8.
\:\\{InitMenus}, 8.
\:\\{InitWindows}, 8.
\:\\{ino\_t}, 54.
\:\\{integer}, 135.
\:\\{ioctl}, 7, 36, \[39], 52.
\:\\{iov}, \[24], \[29].
\:\\{iov\_base}, \[24].
\:\\{iov\_len}, \[24].
\:\\{iovec}, \[24], 27, 29.
\:\\{isatty}, \[58].
\:\\{isTCPDaemon}, \[135], 141.
\:\\{isUDPDaemon}, \[135], 141.
\:\\{len}, 122, \[126], \[127], \[128], \[129].
\:\\{length}, \[82], \[83].
\:\\{level}, \[41], \[42].
\:\\{linkname}, \[68].
\:\\{linkto}, \[68].
\:\\{listen}, 17, \[19], 20, 48, 146.
\:\\{literal}, 135.
\:\\{loc}, \[78].
\:\\{location}, \[95].
\:\\{LocationNameRec}, 95.
\:\\{longint}, \[135].
\:\\{lseek}, \[59].
\:\\{lstat}, \[56], 140.
\:\\{machname}, \[108].
\:\\{malloc}, 73.
\:\\{match}, \[96], 97.
\:\\{MAXNAMLEN}, 74.
\:\\{mkdir}, \[70].
\:\\{MPS}, 135.
\:\\{MPSY}, 137.
\:\\{mpw}, \[135].
\:\\{msg}, \[27], \[32], 131.
\:\\{msg\_accrights}, \[27].
\:\\{msg\_accrightslen}, \[27].
\:\\{msg\_iov}, \[27].
\:\\{msg\_iovlen}, \[27].
\:\\{msg\_name}, \[27].
\:\\{msg\_namelen}, \[27].
\:\\{MSG\_OOB}, 25, 30.
\:\\{msghdr}, \[27], 32.
\:\\{name}, \[16], \[18], 21, \[37], \[38], 50, \[64], \[91], 97, 104, \[113],
116.
\:\\{namelen}, \[18], \[37], \[38].
\:\\{nbpType}, \[96], 97.
\:\\{newcreator}, \[66], \[67].
\:\\{newfd}, \[44].
\:\\{newname}, \[62].
\:\\{newtype}, \[66], \[67].
\:\\{nil}, 8.
\:\\{nlen}, \[16].
\:\\{NLType}, 92.
\:\\{noAutoSpin}, \[135].
\:\\{noTCPDaemon}, \[135], 141.
\:\\{noUDPDaemon}, \[135], 141.
\:\\{NULL}, 20, 26, 34, 73, 75, 76, 81, 104, 105, 112, 115.
\:\\{numTypes}, \[50], \[92].
\:\\{O\_ALIAS}, 63, 146.
\:\\{O\_APPEND}, 63.
\:\\{O\_CREAT}, 63, 64.
\:\\{O\_EXCL}, 63.
\:\\{O\_NRESOLVE}, 146.
\:\\{O\_RDONLY}, 63.
\:\\{O\_RDWR}, 63, 122.
\:\\{O\_RSRC}, 63.
\:\\{O\_TRUNC}, 63, 64.
\:\\{O\_WRONLY}, 64.
\:\\{off\_t}, 54, 82, 83.
\:\\{oldfd}, \[44].
\:\\{oldname}, \[62].
\:\\{open}, \[63], 64, 118, \[119], 122, 145.
\:\\{opendir}, 75.
\:\\{optlen}, \[41], \[42].
\:\\{optname}, \[41], \[42].
\:\\{optval}, \[41], \[42].
\:\\{p\_aliases}, \[115].
\:\\{p\_name}, \[115].
\:\\{p\_proto}, \[115].
\:\\{param}, 131.
\:\\{path}, \[54], \[56], \[69], \[70], \[71], \[72], \[81], \[82].
\:\\{PBHSetVol}, 139.
\:\\{PBSetVol}, 139.
\:\\{port}, \[95], \[114].
\:\\{portType}, 97.
\:\\{PPC\_CON\_MATCH\_NAME}, 97.
\:\\{PPC\_CON\_MATCH\_NBP}, 97.
\:\\{PPC\_CON\_MATCH\_TYPE}, 97.
\:\\{PPC\_CON\_NEWSTYLE}, 97.
\:\\{PPCPortRec}, 95, 96.
\:\\{prompt}, \[16].
\:\\{proto}, 113, 114.
\:\\{protocol}, \[13].
\:\\{protoent}, \[115], 116.
\:\\{Ptr}, 8.
\:\\{qd}, 8.
\:\\{qlen}, \[19].
\:\\{qsort}, 81.
\:\\{read}, 22, \[23], 25, 28, 122, 138, 145.
\:\\{readdir}, 76.
\:\\{readfds}, \[34].
\:\\{readfs}, 34.
\:\\{readlink}, 1, \[69].
\:\\{readv}, 22, \[24], 27.
\:\\{recv}, 22, \[25], 26, 49, 138.
\:\\{recvfrom}, 22, \[26], 27, 49, 145.
\:\\{recvmsg}, 22, \[27], 49.
\:\\{remove}, \[60], 61.
\:\\{rename}, \[62].
\:\\{request}, \[39].
\:\\{rewinddir}, \[79].
\:\\{rmdir}, \[71].
\:\\{routine}, \[132].
\:\\{s\_addr}, \[101].
\:\\{s\_aliases}, \[109].
\:\\{S\_IFCHR}, 55.
\:\\{S\_IFDIR}, 55.
\:\\{S\_IFLNK}, 55.
\:\\{S\_IFREG}, 55.
\:\\{S\_IFSOCK}, 55, 57.
\:\\{s\_name}, \[109].
\:\\{s\_port}, \[109].
\:\\{s\_proto}, \[109].
\:\\{sa\_constr\_atlk}, \[92].
\:\\{sa\_constr\_file}, \[50].
\:\\{sa\_constr\_ppc}, \[96].
\:\\{sade}, 137.
\:\\{scandir}, \[81].
\:\\{seekdir}, \[78].
\:\\{select}, 20, 21, \[34], 51.
\:\\{send}, 22, \[30], 31, 49, 138.
\:\\{sendmsg}, 22, \[32], 49.
\:\\{sendto}, 22, \[31], 32, 49, 145.
\:\\{servent}, \[109], 112, 113, 114.
\:\\{setservent}, \[110].
\:\\{setsockopt}, 36, \[42], 48.
\:\\{SFTypeList}, 50.
\:\\{shutdown}, 122.
\:\\{sin\_addr}, \[101].
\:\\{sin\_family}, \[101].
\:\\{sin\_len}, \[101].
\:\\{sin\_port}, \[101].
\:\\{sin\_zero}, \[101].
\:\\{size}, 73.
\:\\{SOCK\_DGRAM}, 13.
\:\\{SOCK\_STREAM}, 13.
\:\\{sockaddr}, 18, 20, 21, 37, 38.
\:\\{sockaddr\_atlk}, \[90].
\:\\{sockaddr\_atlk\_sym}, \[91].
\:\\{sockaddr\_in}, \[101].
\:\\{sockaddr\_ppc}, \[95].
\:\\{sockaddr\_un}, \[86].
\:\\{Socket}, 145.
\:\\{socket}, 12, \[13], 16, 48, 118, 145.
\:\\{SocketDomain}, 145.
\:\\{sort}, 81.
\:\\{SP\_ADDR}, 131.
\:\\{SP\_AUTO\_SPIN}, 131.
\:\\{SP\_DGRAM\_READ}, 131.
\:\\{SP\_DGRAM\_WRITE}, 131.
\:\\{SP\_MISC}, 131.
\:\\{SP\_NAME}, 131.
\:\\{SP\_SELECT}, 131.
\:\\{SP\_SLEEP}, 131.
\:\\{SP\_STREAM\_READ}, 131.
\:\\{SP\_STREAM\_WRITE}, 131.
\:\\{spin\_msg}, \[131].
\:\\{SpinCursor}, 138.
\:\\{st\_atime}, \[54].
\:\\{st\_blksize}, \[54].
\:\\{st\_blocks}, \[54].
\:\\{st\_ctime}, \[54].
\:\\{st\_dev}, \[54].
\:\\{st\_gid}, \[54].
\:\\{st\_ino}, \[54].
\:\\{st\_mode}, \[54], 55, 57.
\:\\{st\_mtime}, \[54].
\:\\{st\_nlink}, \[54], 140.
\:\\{st\_rdev}, \[54].
\:\\{st\_size}, \[54].
\:\\{st\_uid}, \[54].
\:\\{stat}, \[54], 56, 57, 140.
\:\\{stayopen}, \[110].
\:\\{Str32}, 96.
\:\\{SuffixArray}, 135.
\:\\{sun\_family}, \[86].
\:\\{sun\_path}, \[86].
\:\\{SYM}, 137.
\:\\{symlink}, 1, \[68].
\:\\{s1}, \[129].
\:\\{s2}, \[129].
\:\\{table}, \[133].
\:\\{tcpDaemon}, 143.
\:\\{TEInit}, 8.
\:\\{telldir}, \[77].
\:\\{text}, \[135].
\:\\{TEXT}, 135.
\:\\{thePort}, 8.
\:\\{time\_t}, 54.
\:\\{timeout}, \[34].
\:\\{timeval}, 34.
\:\\{to}, \[31], \[128].
\:\\{tolen}, \[31].
\:\\{truncate}, \[82].
\:\\{type}, \[13], \[16].
\:\\{types}, \[50], \[92].
\:\\{u\_char}, 101.
\:\\{u\_long}, 74, 101.
\:\\{u\_short}, 54, 74, 101.
\:\\{udpDaemon}, 143.
\:\\{unlink}, \[61].
\:\\{useChdir}, \[135], 139.
\:\\{WaitNextEvent}, 133, 134.
\:\\{want}, \[81].
\:\\{wide}, 135.
\:\\{width}, \[34].
\:\\{WR\_ONLY}, 63.
\:\\{write}, 22, \[28], 30, 122, 138, 145.
\:\\{writefds}, \[34].
\:\\{writefs}, 34.
\:\\{writev}, 22, \[29], 32.
\fin
\con
